perm filename EMITER.SAI[OLD,HE] blob sn#463356 filedate 1979-08-02 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00003 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	ENTRY  COMMENT COMERR, GENLABEL, INITOUT, CLOSEOUT
C00006 00003	!  MAKE_REMARK, EMIT
C00010 ENDMK
C⊗;
ENTRY;  COMMENT COMERR, GENLABEL, INITOUT, CLOSEOUT;
BEGIN "emiter"

REQUIRE "ABBREV.SAI[AL,HE]" SOURCE_FILE;
REQUIRE "EMITER.HDR[AL,HE]" SOURCE_FILE;

INTERNAL PROCEDURE COMERR
  (STRING MESSG;RECORD_POINTER(ANY_CLASS) CONTXT (NULL_RECORD));
    !  Non-fatal warnings;
    BEGIN
    EXTERNAL RECURSIVE PROCEDURE ALPRIN
     (RECORD_POINTER(ANY_CLASS) S);
    IF CONTXT≠NULL_RECORD THEN ALPRIN(CONTXT);
    USERERR(0,1,"HAH!  "&MESSG);
    END;

INTERNAL INTEGER PROCEDURE GENLABEL;
    BEGIN  ! Makes a new label for the PALX output;
    OWN INTEGER LAB;
    RETURN(LAB ← LAB + 1);
    END;

INTEGER REL0;  !  Channel number;
INTEGER REL1;  !  Channel number;
INTEGER REL2;  !  Channel number;
INTEGER REL3;  !  Channel number;
BOOLEAN SYM_FILE;	! If true generate a symbol file, else don't;

INTERNAL PROCEDURE INITOUT(STRING FNAME,PPN; BOOLEAN SF(TRUE));
    BEGIN "initout" ! Initialize the four output streams, going to the files
    FNAME.ALP, FNAME.ALT, FNAME.ALV, FNAME.ALS;
    INTEGER COUNT, BRCHAR, EOF, FLAG;
    REL0 ← GETCHAN;
    OPEN(REL0,"DSK",0,0,2,COUNT,BRCHAR,EOF);
    ENTER(REL0,FNAME&".ALP"&PPN,FLAG);
    IF FLAG THEN COMERR("I can't enter "&FNAME&".ALP");
    REL1 ← GETCHAN;
    OPEN(REL1,"DSK",0,0,2,COUNT,BRCHAR,EOF);
    ENTER(REL1,FNAME&".ALT"&PPN,FLAG);
    IF FLAG THEN COMERR("I can't enter "&FNAME&".ALT");
    REL2 ← GETCHAN;
    OPEN(REL2,"DSK",0,0,2,COUNT,BRCHAR,EOF);
    ENTER(REL2,FNAME&".ALV"&PPN,FLAG);
    IF FLAG THEN COMERR("I can't enter "&FNAME&".ALV");
    IF SF THEN
	BEGIN
	REL3 ← GETCHAN;
	OPEN(REL3,"DSK",0,0,2,COUNT,BRCHAR,EOF);
	ENTER(REL3,FNAME&".ALS"&PPN,FLAG);
	IF FLAG THEN COMERR("I can't enter "&FNAME&".ALS");
	SYM_FILE ← TRUE
	END
    ELSE SYM_FILE ← FALSE
    END "initout";

INTERNAL PROCEDURE CLOSEOUT;
    BEGIN  ! Close all channels;
    CLOSE(REL0);
    CLOSE(REL1);
    CLOSE(REL2);
    IF SYM_FILE THEN CLOSE(REL3);
    END;
!  MAKE_REMARK, EMIT;

STRING RSTRING;

INTERNAL PROCEDURE EMIT(INTEGER PC; REFERENCE INTEGER DATA, RELOC;
    INTEGER LTH (1));
    BEGIN "emit"
    !  Appends to current PAL files.  DATA and RELOC are the first
    words in a block of size LTH.  DATA holds the actual output, and
    RELOC holds relocation information about how to treat the word in
    DATA.  A record is kept of how many bytes have been stored for
    each PC;

    OWN INTEGER ARRAY WORDCOUNT [0:3];	!  How many words have been stored
	for this PC;

    INTEGER J, K, DAT, REL;
    EXTERNAL STRING ARRAY PSOP[1:300];
    IF PC = SYMFIL ∧ ¬SYM_FILE THEN RETURN;
    REL ← CASE PC OF (REL0, REL1, REL2, REL3);

    FOR J ← 0 STEP 1 UNTIL LTH-1 DO
	BEGIN "emitloop"
	DAT ← MEMORY[LOC(DATA) + J];
	CASE MEMORY[LOC(RELOC) + J] OF
	    BEGIN "case"
   [PSINST]	BEGIN "psinst"
		IF PC ≠ PSDCODE
		THEN COMERR("Outputting a pseudo-instruction, PC is not PSDCODE.");
		OUT(REL,TAB & PSOP[DAT] & CRLF);
		WORDCOUNT[PC] ← WORDCOUNT[PC] + 1;
		END "psinst";
   [SYMDEC]	OUT(REL,"L" & CVOS(DAT) & ":");
   [SYMREF]	BEGIN "symref"
		OUT(REL,(TAB & "L") & CVOS(DAT) & CRLF);
		WORDCOUNT[PC] ← WORDCOUNT[PC] + 1;
		END "symref";
   [REMARK]	OUT(REL,(TAB & TAB & ";") & RSTRING & CRLF);
   [SKIP]	BEGIN "skip"
		OUT(REL,(TAB & ".BLKW" & TAB) & CVOS(DAT) & CRLF);
		WORDCOUNT[PC] ← WORDCOUNT[PC] + DAT;
		END "skip";
   [CONST]	BEGIN "const"
		OUT(REL,TAB & CVOS(DAT LAND '177777) & CRLF);
		WORDCOUNT[PC] ← WORDCOUNT[PC] + 1;
		END "const";
   [FLOAT]	BEGIN "float"
		OUT(REL,TAB & ".FLT2" & TAB & CVF(MEM[LOC(DAT),REAL]) & CRLF);
		WORDCOUNT[PC] ← WORDCOUNT[PC] + 2;
		END "float";
   [STRCONST]	BEGIN "strconst"
		!  DAT is the location of a string constant;
		STRING STR;
		MEMLOC(STR,INTEGER) ← DAT;
		MEMLOC(STR,INTEGER) ← MEM[DAT,INTEGER];
		MEM[LOC(STR)-1,INTEGER] ← MEM[DAT-1,INTEGER];
		OUT(REL,TAB & "ASCIE ↑∀" & STR & "∀" & CRLF);
		WORDCOUNT[PC] ← WORDCOUNT[PC] + (LENGTH(STR)+1) DIV 2;
		END "strconst"
	    END "case";
	END "emitloop";
    END "emit";

INTERNAL PROCEDURE MAKE_REMARK(INTEGER PC;STRING REMK);
    BEGIN "make_remark"  !  Outputs this remark to the PAL file;
    RSTRING ← REMK;
    EMIT(PC,0,REMARK);
    END "make_remark";

END "emiter";